package top.dyzmj.detty.core.utils.internal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.dyzmj.detty.core.utils.SystemPropertyUtil;

import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.regex.Pattern;

/**
 * 描述: 检测特定于当前运行时环境的各种属性的实用程序，例如Java版本和  {@code sun.misc.Unsafe} 对象的可用性。
 * 如果你指定了系统属性 <strong>io.netty.noUnsafe</strong>，你可以禁用 {@code sun.misc.Unsafe}.
 *
 * @author dongYu
 * @date 2021/11/18
 */
public class PlatformDependent {

	private final static Logger logger = LoggerFactory.getLogger(PlatformDependent.class);

	private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
			"\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");

	private static final boolean HAS_UNSAFE = hasUnsafe0();

	private static final boolean DIRECT_BUFFER_PREFERRED = HAS_UNSAFE;
	private static final String NORMALIZED_OS = normalizeOs(SystemPropertyUtil.get("os.name", ""));
	private static final boolean IS_WINDOWS = isWindows0();

//	private static final long MAX_DIRECT_MEMORY = maxDirectMemory0();

//	private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0();

	static {
		if (logger.isDebugEnabled()) {
			logger.debug("-Dio.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED);
		}

		if (!hasUnsafe()) {
			logger.info("Your platform does not provide complete low-level API for accessing direct buffers reliably. " +
					"Unless explicitly requested, heap buffer will always be preferred to avoid potential system " +
					"unstability.");
		}

	}

	private PlatformDependent() {
	}

	public static boolean hasUnsafe() {
		return HAS_UNSAFE;
	}

	public static boolean isWindows() {
		return IS_WINDOWS;
	}

	/**
	 * 如果平台有可靠的底层直接缓存访问API，并且用户指定了{@code-preferdirect}选项，则返回{@code true}。
	 */
	public static boolean directBufferPreferred() {
		return DIRECT_BUFFER_PREFERRED;
	}

	/**
	 * 尝试释放指定的直接{@link ByteBuffer}。
	 * 请注意，如果当前平台不支持此操作，或者指定的缓冲区不是直接缓冲区。
	 */
	public static void freeDirectBuffer(ByteBuffer buffer) {
		if (hasUnsafe()) {
			PlatformDependent0.freeDirectBuffer(buffer);
		}
	}

	@SuppressWarnings("unchecked")
	private static <E extends Throwable> void throwException0(Throwable t) throws E {
		throw (E) t;
	}

	/**
	 * 引发绕过编译器检查受控异常的 异常。
	 */
	public static void throwException(Throwable t) {
		if (hasUnsafe()) {
			PlatformDependent0.throwException(t);
		} else {
			PlatformDependent.throwException0(t);
		}
	}

	public static long directBufferAddress(ByteBuffer buffer) {
		return PlatformDependent0.directBufferAddress(buffer);
	}

	public static int javaVersion() {
		return PlatformDependent0.javaVersion();
	}

	private static boolean isWindows0() {
		boolean windows = "windows".equals(NORMALIZED_OS);
		if (windows) {
			logger.debug("Platform: Windows");
		}
		return windows;
	}


	private static boolean hasUnsafe0() {
		try {
			boolean hasUnsafe = PlatformDependent0.hasUnsafe();
			logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
			return hasUnsafe;
		} catch (Throwable t) {
			return false;
		}
	}

	private static String normalize(String value) {
		return value.toLowerCase(Locale.CHINESE).replaceAll("[^a-z0-9]+", "");
	}

	/**
	 * 规范化系统名称
	 */
	private static String normalizeOs(String value) {
		value = normalize(value);
		if (value.startsWith("linux")) {
			return "linux";
		}
		if (value.startsWith("macosx") || value.startsWith("osx") || value.startsWith("darwin")) {
			return "osx";
		}
		if (value.startsWith("windows")) {
			return "windows";
		}
		return "unknown";
	}

}
